#ifndef IVARIANT_TEST_H
#define IVARIANT_TEST_H

#include "include/gtest.h"
#include "../Tool/include/Variant.h"
#include "../Tool/include/ILogger.h"
#include "../Tool/include/Timer.h"
#include <iostream>
#include "nlohmann/json.hpp"

using namespace Tool;
using namespace std;

struct Point
{
    Point()
        : x(0), y(0)
    {
    }
    Point(int x, int y)
        : x(x), y(y)
    {
    }
    friend std::ostream &operator<<(std::ostream &os, const Point &point)
    {
        os << "point x:" << point.x << " y:" << point.y;
        return os;
    }

    // 序列化函数
    static void Serialize(const std::any &data, uint8_t* buffer, size_t offset)
    {
        const Point &point = std::any_cast<const Point &>(data);
        memcpy(buffer + offset, &point, sizeof(Point));
        offset += sizeof(Point);
    }

    // 反序列化函数
    static std::any Deserialize(const uint8_t* buffer, size_t offset)
    {
        Point point;
        memcpy(&point, buffer, sizeof(Point));
        offset += sizeof(Point);
        return point;
    }

    static void SerializeJson(const std::any &data, VariantHash &variant)
    {
        const Point &point = std::any_cast<const Point &>(data);
        variant["x"] = point.x;
        variant["y"] = point.y;
    }

    static std::any DeserializeJson(VariantHash &variant)
    {
        Point point(variant["x"], variant["y"]);
        return point;
    }
    int x;
    int y;
};

TEST(Variant, Variantvariant)
{
    Variant::RegisterType<Point>(Point::Serialize, Point::Deserialize);
    Variant::RegisterJsonType<Point>(Point::SerializeJson, Point::DeserializeJson);

    int count = 1000;
    Timer timer;
    VariantVector maps(count);
    for(int i = 0; i < count; ++i)
    {
        VariantVector vec(count);
        for(int j = 0; j < count; ++j)
        {
            Variant map;
            map["angle"] = 90;
            map["id"] = "20250617102731038";
            map["x"] = -10.675;
            map["groupName"] = "A";
            map["name"] = "E4";
            map["block"] = 1;
            map["height"] = 0;
            map["y"] = 21.394;
            vec[j] = map;
        }
        maps[i] = vec;
    }
    std::cout << "数量: "<< count << "，耗时: " << timer.Elapsed() << std::endl;

    timer.Reset();
    nlohmann::json maps1;
    for(int i = 0; i < count; ++i)
    {
        nlohmann::json vec;
        for(int j = 0; j < count; ++j)
        {
            nlohmann::json map;
            map["angle"] = 90;
            map["id"] = "20250617102731038";
            map["x"] = -10.675;
            map["groupName"] = "A";
            map["name"] = "E4";
            map["block"] = 1;
            map["height"] = 0;
            map["y"] = 21.394;
            vec.push_back(map);
        }
        maps1.push_back(vec);
    }
    std::cout << "数量: "<< count << "，耗时: " << timer.Elapsed() << std::endl;
    return;

    VariantMap variantMap;
    VariantSet variantSet;
    VariantHash variantHash;
    std::vector<Variant> variantvector;
    variantMap["1"] = 100;
    variantMap["2"] = 120.12;
    variantMap["3"] = "你好";
    variantMap["4"] = true;
    variantMap["5"] = Variant::FromValue<Point>(Point(20, 20));
    VariantList variantList;
    variantList.emplace_back(101);
    variantList.emplace_back(121.12);
    variantList.emplace_back("hellow");
    variantList.emplace_back(false);
    variantList.emplace_back(Variant::FromValue<Point>(Point(30, 30)));
    variantMap["5"] = variantList;
    variantSet.emplace(200);
    variantSet.emplace(200.12);
    variantSet.emplace("hellow every bady");
    variantSet.emplace(false);
    variantMap["6"] = variantSet;
    variantHash["1"] = 101;
    variantHash["2"] = 121.12;
    variantHash["3"] = "都好都好";
    variantHash["4"] = true;
    variantMap["7"] = variantHash;
    variantvector.emplace_back(103);
    variantvector.emplace_back(103.12);
    variantvector.emplace_back(false);
    variantMap["8"] = Variant::FromValue<std::vector<Variant>>(variantvector);

    std::cout << "vector: " << variantvector << std::endl;
    std::cout << "list: " << variantList << std::endl;
    std::cout << "set: " << variantSet << std::endl;
    std::cout << "hash: " << variantHash << std::endl;
    std::cout << "map: " << variantMap << std::endl;
    Variant serialize = variantMap;
    serialize.SerializeToFile("serialize.bin", VariantSerializeType::Binary);

    int value = variantMap["8"][0];
    LOG_INFO("vector value: %d", value);
    variantMap["8"][0] = 104;
    LOG_INFO("vector value: %d", static_cast<int>(variantMap["8"][0]));
    LOG_INFO("vector: %s", Variant(variantvector).ToJsonString().c_str());

    VariantHash hash = variantMap["7"];
    VariantHash &hash1 = variantMap["7"];
    VariantHash hash2 = variantMap["7"].ToHash();
    hash1["1"] = 120;
    variantMap["7"] = 12;
    Variant serialize5 = serialize["1"];
    Variant serialize6;
    serialize6["1"] = 2;
    Variant serialize7;
    serialize7[2] = 2;
    serialize7[0] = "你好世界";
    std::string str = serialize7[0];
    LOG_INFO("vector value index 1: %d", static_cast<int>(serialize7[1]));
    LOG_INFO("vector value index 2: %d", static_cast<int>(serialize7[2]));
    LOG_INFO("vector value index 0: %s", static_cast<std::string>(serialize7[0]).c_str());
    std::string &str1 = serialize7[0];
    str1 = "你也好，世界";
    LOG_INFO("vector value index 0: %s", static_cast<std::string>(serialize7[0]).c_str());

    Variant serialize2;
    serialize2.DeserializeFromFile("serialize.bin", VariantSerializeType::Binary);
    VariantMap variantMap2 = serialize2.ToMap();
    std::cout << "从二进制反序列化map: " << serialize2 << std::endl;

    std::cout << "序列化之前: " << serialize << std::endl;
    std::cout << "从二进制反序列化: " << serialize2 << std::endl;

    variantvector = variantMap["8"].Value<std::vector<Variant>>();
}

TEST(Variant, VariantvariantDeserialize)
{
    Variant variant;
    variant["1"] = 100;
    variant["2"] = { 120, 30.2, "hellow"};
    variant["3"] = Variant(variant);
    variant["4"] = Variant::FromValue<Point>(Point(20, 20));

    Variant variant1, variant2, variant3, variant4, variant5;
//    variant1.DeserializeFromFile("aa.json", VariantSerializeType::Json);
//    std::cout << variant1 << std::endl;

    LOG_INFO("初始: %s", variant.ToJsonString().c_str());
    const std::vector<uint8_t> &bstr = variant.ToBinaryString();
    Variant bstr1;
    bstr1.FromBinaryString(bstr);
    LOG_INFO("FromBinaryString: %s", bstr1.ToJsonString().c_str());

    variant2 = Variant(variant);
    variant2.SerializeToFile("bb123.bin");

    variant3.DeserializeFromFile("bb123.bin");
    LOG_INFO("FromBinaryFile: %s", variant3.ToJsonString().c_str());

    variant4 = variant;
    variant4.SerializeToFile("bb.json", VariantSerializeType::Json);

    variant5.DeserializeFromFile("bb.json", VariantSerializeType::Json);
    LOG_INFO("FromJsonFile: %s", variant5.ToJsonString().c_str());
}


TEST(Variant, VariantvariantFile)
{
//    return;
    Timer timer;
    Variant variant;
    variant["path"] = "aa";
    std::ifstream file("aa.7z", std::ios::binary);
    if (!file.is_open())
    {
        std::cout << "打开文件失败: " << variant["path"] << std::endl;
        return;
    }
    std::vector<uint8_t> data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
    LOG_INFO("读取文件耗时 %f毫秒", timer.Elapsed());
    timer.Reset();

    variant["data"] = std::move(data);
    file.close();

    LOG_INFO("variant写入文件 %f毫秒", timer.Elapsed());
    timer.Reset();

    variant.SerializeToFile("aa.7z.bin");

    LOG_INFO("variant 序列化文件 %f毫秒", timer.Elapsed());
    timer.Reset();

    Variant variant2;
    variant2.DeserializeFromFile("aa.7z.bin");
    
    LOG_INFO("variant 反序列化文件 %f毫秒", timer.Elapsed());
    timer.Reset();

    std::ofstream file2("aa1.7z", std::ios::binary);
    std::vector<uint8_t> & data2 = variant2["data"].ToBinary();
    file2.write(reinterpret_cast<const char*>(data2.data()), data2.size());
    file2.close();
    LOG_INFO("文件写入 %f毫秒", timer.Elapsed());
    timer.Reset();
}

TEST(Variant, VariantvariantEqual)
{
    Variant variant;
    int count = 10;
    for (int i = 0; i < count; ++i)
    {
        Variant hash;
        hash["a"] = i;
        hash["b"] = (i % 2 == 0);
        hash["c"] = "value" + to_string(i);
        hash["d"] = static_cast<double>(i) / 100.0;
        variant[to_string(i)] = std::move(hash);
    }
    Variant varian1 = variant;
    LOG_INFO("赋值后 Equal： %d", varian1 == variant);

    Variant varian3;
    for (int i = 0; i < count; ++i)
    {
        Variant hash;
        hash["a"] = i;
        hash["b"] = (i % 2 == 0);
        hash["c"] = "value" + to_string(i);
        hash["d"] = static_cast<double>(i) / 100.0;
        varian3[to_string(i)] = std::move(hash);
    }
    LOG_INFO("同样赋值后 Equal： %d", varian3 == variant);

    variant.SerializeToFile("VariantvariantEqual.bin");
    Variant varian4;
    varian4.DeserializeFromFile("VariantvariantEqual.bin");
    LOG_INFO("二进制序列化后 Equal： %d", varian4 == variant);

    variant.SerializeToFile("VariantvariantEqual.json", VariantSerializeType::Json);
    Variant varian5;
    varian5.DeserializeFromFile("VariantvariantEqual.json", VariantSerializeType::Json);
    LOG_INFO("json序列化后 Equal： %d", varian5 == variant);
    varian5.SerializeToFile("VariantvariantEqual5.json", VariantSerializeType::Json);
    Variant varian6;
    varian6.DeserializeFromFile("VariantvariantEqual5.json", VariantSerializeType::Json);
    LOG_INFO("json序列化后 Equal： %d", varian5 == varian6);
}
#endif // IVARIANT_TEST_H
